parser grammar AnalexCParser;

options {
  language = Java;
  tokenVocab = AnalexCLexer;
}

@header {
  package Practica8.Sintactico;
  import java.util.ArrayList;
  import java.util.List;
}

@members {
  private ArrayList<String> errors = new ArrayList<String>();
  public void displayRecognitionError(String[] tokenNames, RecognitionException e) {
    String hdr = getErrorHeader(e);
    String msg = getErrorMessage(e, tokenNames);
    errors.add(hdr + " " + msg);
  }
   
  public ArrayList<String> getErrors() {
    return errors;
  }
}

entrada : (sentencias)*;

sentencias
  : (typesc ID LEFT_PAREN) => f = funcion { System.out.println(f); }
  | statement = sentencia { System.out.println(statement); }
  ;

typesc returns [String type]
  : tipo = DATO_TIPO  { type = tipo.getText(); }
  | tvoid = KEYWORD_VOID { type = tvoid.getText(); }
  ;
  
funcion returns [String res]
  : h = cabecera 
   bl = block {
      res = h + " " + bl;
   }
  ;

cabecera returns [String h]
  : tipo = typesc     { h = tipo; }
    var = ID          { h += " " + var.getText(); } 
    lp = LEFT_PAREN   { h += " " + lp.getText(); } 
  (  v = KEYWORD_VOID { h += v.getText(); }
  | par = params      { h += par; }
  )  rp = RIGHT_PAREN { h += rp.getText(); } 
  ;

params  returns [String par]
  : ( tipo = DATO_TIPO { par = tipo.getText(); }) 
       var = ID        { par += " " + var.getText(); }
    (comma = COMA      { par += comma.getText(); }
  ( tipo = DATO_TIPO   { par = tipo.getText(); }) 
     var = ID          { par += " " + var.getText(); })*
  ; 

block returns [String bl = ""] @init{ List<String> list = new ArrayList<String>(); }
  : lb = LEFT_BRACE               { bl += lb.getText() + "\r\n"; } 
   (statement = sentencia { list.add (statement);})+
    {
      for (Integer i = 0; i < list.size(); i++)
        bl += list.get(i);
    }
    rb = RIGHT_BRACE              { bl += rb.getText() + "\r\n"; }  
  ;
  
sentencia returns [String res]
  : dec  = declaracion       { res = dec; }
  | asig = asignacion        { res = asig; }
  | whi  = whileblock        { res = whi; }
  | ifb  = ifblock           { res = ifb; }
  | fun  = funcionInstancia  { res = fun; }
  | bre  = abortstatement    { res = bre; } 
  ;
  
declaracion returns [String dec]
  : ( tipo = DATO_TIPO   { dec = tipo.getText();}) 
       var = ID          { dec += " " + var.getText(); }
    (comma = COMA        { dec += comma.getText(); } 
       var = ID          { dec += " " + var.getText(); })* 
       sep = SEPARADOR   { dec += sep.getText() + "\r\n"; } 
  ;
  
asignacion returns [String asig]
  : var = ID        { asig = var.getText(); } 
   ( op = OP_ASSIGN { asig += " " + op.getText() + " "; } e = expresion { asig += e; })* 
    sep = SEPARADOR { asig += sep.getText() + "\r\n"; }
  ;
  
funcionInstancia returns [String fci]
  : id = ID          { fci = id.getText(); } 
    lp = LEFT_PAREN  { fci += lp.getText(); } 
   val = values      { fci += val; } 
    rp = RIGHT_PAREN { fci += rp.getText(); } 
   sep = SEPARADOR   { fci += sep.getText() + "\r\n"; }
  ;
 
values returns [String val = ""]
  : (id = ID       { val = id.getText(); }
  | str = STRING   { val = str.getText(); })? 
  (comma= COMA     { val += comma.getText() + " "; }
  (  id = ID       { val += id.getText(); }
  |  str= STRING   { val += str.getText(); }))*
  ;
  
expresion returns [String expr = ""]
  : (sum = OP_SUM          {expr = sum.getText();} 
  |  sub = OP_SUB          {expr = sub.getText();})? 
      op = operacion       {expr += op;} 
  (   qm = OP_QUESTIONMARK {expr += qm.getText();}
     opp = operacion       {expr += opp;} 
     cln = OP_COLON        {expr += cln.getText();} 
    opp2 = operacion       {expr += opp2;})?
  ;
  
  
operacion returns [String op = ""]
  : sum    = suma   {op = sum;} 
  ((op_sum = OP_SUM {op += op_sum.getText();} 
  | op_sub = OP_SUB {op += op_sub.getText();})
  | sum2   = suma   {op += sum2;})*
  ;


suma returns [String suma = ""]
  : mult    = producto {suma = mult;} 
  ((op_mult = OP_MULT {suma += op_mult.getText();}
  | op_div  = OP_DIV    {suma += op_div.getText();})
    mult2   = producto   {suma += mult2;})*
  ;


producto returns [String prod = ""]
  : prop   = proposicion {prod = prop;}
  ((op_and = OP_AND      {prod += op_and.getText();}
  | op_or  = OP_OR       {prod += op_or.getText();})
    prop2  = proposicion {prod += prop2;})*
  ;


proposicion returns [String prop = ""]
  : (op_not = OP_EXCLA    {prop = op_not.getText();})?
     cmp    = comparacion {prop += cmp;}
  ;

comparacion returns [String cmp = ""]
  : fc     = factor {cmp = fc;} 
  ( op_cmp = CMP_SYMBOL {cmp += op_cmp.getText();}
    fc2    = factor {cmp += fc2;})? 
  ;


factor returns [String fac]
  : (car = CARACTER {fac = car.getText();}
  |  num = NUMERO   {fac = num.getText();}
  |  id  = ID       {fac = id.getText();})
  | (lp  = LEFT_PAREN {fac += lp.getText();}
     exp = expresion {fac += exp;} 
     rp  = RIGHT_PAREN {fac += rp.getText();})
  ;


whileblock returns [String wl]
  : w = KEYWORD_WHILE     { wl = w.getText(); } 
   lp = LEFT_PAREN        { wl += " " + lp.getText(); }
  exp = expresion         { wl += exp; }
   rp = RIGHT_PAREN       { wl += rp.getText()+ " "; }
  (bl = block             { wl += bl; }
  |st = sentencia         { wl += "\r\n" + st; })
  ; 

ifblock returns [String ib]
  : iw = KEYWORD_IF        { ib = iw.getText(); } 
    lp = LEFT_PAREN        { ib += " " + lp.getText(); } 
   exp = expresion         { ib += exp; } 
    rp = RIGHT_PAREN       { ib += rp.getText() + " "; } 
   (bl = block             { ib += bl; } 
   |st = sentencia         { ib += "\r\n" + st; })
  ;
  
abortstatement returns [String bs]
  : br = KEYWORD_BREAK    { bs = br.getText(); }   
   sep = SEPARADOR        { bs += sep.getText();}
  ;
  